package top.whysu.edevice.service.manage.impl;

import com.alibaba.fastjson.JSON;
import com.feilong.lib.lang3.StringUtils;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import top.whysu.edevice.constant.CodeConstant;
import top.whysu.edevice.constant.DataDictionary;
import top.whysu.edevice.dao.manage.ManageVoucherDao;
import top.whysu.edevice.dao.relative.RelativeVoucherAccountDao;
import top.whysu.edevice.dao.system.AccountDao;
import top.whysu.edevice.dto.manage.*;
import top.whysu.edevice.dto.page.PagenationDataDTO;
import top.whysu.edevice.exception.BusinessException;
import top.whysu.edevice.po.manage.ManageVoucherPO;
import top.whysu.edevice.po.relative.RelativeVoucherAccountPO;
import top.whysu.edevice.po.system.AccountPO;
import top.whysu.edevice.service.ezviz.EzvizHttpService;
import top.whysu.edevice.service.ezviz.EzvizService;
import top.whysu.edevice.service.ezviz.EzvizTokenService;
import top.whysu.edevice.service.manage.ManageTreeService;
import top.whysu.edevice.service.manage.ManageVoucherService;
import top.whysu.edevice.service.relative.RelativeVoucherAccountService;
import top.whysu.edevice.service.system.AccountService;
import top.whysu.edevice.utils.PageUtils;
import top.whysu.edevice.utils.ShareCodeUtil;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;

@Service("ManageVoucherServiceImpl")
public class ManageVoucherServiceImpl implements ManageVoucherService {

    private static final Logger LOGGER = LoggerFactory.getLogger(ManageVoucherServiceImpl.class);

    @Resource
    private ManageVoucherDao manageVoucherDao;
    @Resource
    private AccountService accountService;
    @Resource
    private RelativeVoucherAccountService relativeVoucherAccountService;
    @Resource
    private RelativeVoucherAccountDao relativeVoucherAccountDao;
    @Resource
    private ManageTreeService manageTreeService;
    @Resource
    protected AccountDao accountDao;
    @Resource
    private EzvizHttpService ezvizHttpService;
    @Resource
    private EzvizTokenService ezvizTokenService;
    @Resource
    private EzvizService ezvizService;

    @Override
    public BigDecimal wholeAddModifyVoucher(VoucherAddModifyDTO addModifyDTO) {
        // id
        BigDecimal id = addModifyDTO.getId();
        String voucherName = addModifyDTO.getVoucherName();
        // 当前操作用户
        String currentUser = accountService.getCurrentLoginUser();
        // 校验凭证组名称
        validateVoucherName(voucherName, id);
        if (id != null) {
            // 编辑，根据id查询
            ManageVoucherPO manageVoucherPO = getVoucherById(id);
            // 修改树结构对应的名称
            NodeEditDTO nodeEditDTO = new NodeEditDTO();
            nodeEditDTO.setId(manageVoucherPO.getTreeId());
            nodeEditDTO.setName(voucherName);
            manageTreeService.wholeModifyNode(nodeEditDTO);
            // 修改名称
            manageVoucherPO.setVoucherName(voucherName);
            // 当前操作用户
            manageVoucherPO.setUpdateBy(currentUser);
            manageVoucherPO.setUpdateTime(new Date());
            manageVoucherDao.update(manageVoucherPO);
        } else {
            // 新增
            ManageVoucherPO po = new ManageVoucherPO();
            BeanUtils.copyProperties(addModifyDTO, po);
            // 新增树节点
            NodeAddDTO nodeAddDTO = new NodeAddDTO();
            nodeAddDTO.setPid(new BigDecimal(0));
            nodeAddDTO.setName(voucherName);
            nodeAddDTO.setNodeType(DataDictionary.NodeType.VOUCHER_TYPE);
            BigDecimal treeId = manageTreeService.wholeAddNode(nodeAddDTO);
            po.setTreeId(treeId);
            // 邀请码
            po.setVoucherNo(generateVoucherNo());
            po.setCreateBy(currentUser);
            po.setCreateTime(new Date());
            po.setUpdateBy(currentUser);
            po.setUpdateTime(new Date());
            manageVoucherDao.insert(po);
            // 获得新增的id
            id = po.getId();
        }
        return id;
    }

    @Override
    public void wholeDeleteVoucher(BigDecimal id) {
        // 校验id是否存在
        getVoucherById(id);
        // 查询是否有关联的账号
        List<BigDecimal> accountIdList = relativeVoucherAccountDao.queryAccountIdList(id);
        if (CollectionUtils.isNotEmpty(accountIdList)) {
            throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "请先清空当前凭证下绑定的账号！");
        }
        // 删除
        manageVoucherDao.deleteById(id);
    }

    @Override
    public PagenationDataDTO<ManageVoucherPO> selectPage(VoucherQueryDTO voucherQueryDTO) {
        // 获取集合
        LinkedHashMap queryMap = JSON.parseObject(JSON.toJSONString(voucherQueryDTO), LinkedHashMap.class);
        // limit的起始值
        queryMap.put("rowIndex", PageUtils.getRowIndex(voucherQueryDTO.getPageNum(), voucherQueryDTO.getPageSize()));
        List<ManageVoucherPO> list = manageVoucherDao.queryAllByLimit(queryMap);
        // 获取总数
        long totalSize = manageVoucherDao.count(queryMap);
        if (CollectionUtils.isNotEmpty(list) && totalSize > 0) {
            return new PagenationDataDTO<>(totalSize, voucherQueryDTO.getPageNum(), voucherQueryDTO.getPageSize(), list);
        } else {
            return PageUtils.toPagedResult(null);
        }
    }

    @Override
    public String generateVoucherNo() {
        String generateCode = ShareCodeUtil.generateCode();
        // 查询邀请码是否在数据库中已存在, 如果存在的话再次生成
        if (manageVoucherDao.queryByVoucherNo(generateCode) != null) {
            generateCode = generateVoucherNo();
        }
        return generateCode;
    }

    @Override
    public PagenationDataDTO<AssignAccountPageDTO> getAssignAccountPage(AssignAccountQueryDTO queryDTO) {
        // 获取集合
        LinkedHashMap queryMap = JSON.parseObject(JSON.toJSONString(queryDTO), LinkedHashMap.class);
        // limit的起始值
        queryMap.put("rowIndex", PageUtils.getRowIndex(queryDTO.getPageNum(), queryDTO.getPageSize()));
        List<AssignAccountPageDTO> list = manageVoucherDao.getAssignAccountPage(queryMap);
        // 获取总数
        long totalSize = manageVoucherDao.countAccountByVoucherId(queryDTO.getVoucherId());
        if (CollectionUtils.isNotEmpty(list) && totalSize > 0) {
            return new PagenationDataDTO<>(totalSize, queryDTO.getPageNum(), queryDTO.getPageSize(), list);
        } else {
            return PageUtils.toPagedResult(null);
        }
    }

    @Override
    public BigDecimal wholeAddAssignAccount(AssignAccountAddDTO addDTO) {
        BigDecimal voucherId = addDTO.getVoucherId();
        if (voucherId == null || StringUtils.isBlank(addDTO.getUsername())) {
            throw new BusinessException(CodeConstant.Http.INFO_ERROR, "参数错误！");
        }
        // 查询账号是否存在
        AccountPO accountPO = accountService.selectByUsername(addDTO.getUsername());
        if (accountPO == null || accountPO.getId() == null) {
            throw new BusinessException(CodeConstant.Http.INFO_ERROR, "要关联的账号不存在！（注意请填写完整的账号，并且不是昵称）");
        }
        BigDecimal accountId = accountPO.getId();
        // 查看关联关系是否存在
        RelativeVoucherAccountPO queryPO = new RelativeVoucherAccountPO();
        queryPO.setAccountId(accountId);
        List<RelativeVoucherAccountPO> poList = relativeVoucherAccountDao.queryAll(queryPO);
        if (CollectionUtils.isNotEmpty(poList)) {
            poList.forEach(it -> {
                if (voucherId.equals(it.getVoucherId())) {
                    throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "当前账号已关联当前凭证组，无需再次添加！");
                } else {
                    throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "当前账号已关联其它凭证组，不允许添加多次！");
                }
            });
        }
        // 新增
        RelativeVoucherAccountPO insertPO = new RelativeVoucherAccountPO();
        insertPO.setVoucherId(voucherId);
        insertPO.setAccountId(accountId);
        String currentUser = accountService.getCurrentLoginUser();
        insertPO.setCreateBy(currentUser);
        insertPO.setUpdateBy(currentUser);
        insertPO.setCreateTime(new Date());
        insertPO.setUpdateTime(new Date());
        relativeVoucherAccountDao.insert(insertPO);
        // 在萤石新增子账号
        ezvizService.createChildAccount(accountId, voucherId);
        // 授权子账号权限
        ezvizService.setPolicyAfterAssignAccount(accountId, voucherId);
        return insertPO.getId();
    }

    @Override
    public void wholeDeleteVoucherAccountRelative(BigDecimal relativeId) {
        if (relativeId == null) {
            throw new BusinessException(CodeConstant.Http.INFO_ERROR, "id不能为空！");
        }
        RelativeVoucherAccountPO relativePO = relativeVoucherAccountDao.queryById(relativeId);
        if (relativePO != null) {
            // 删除萤石上的子账号
            ezvizService.deleteChildAccount(relativePO.getAccountId(), relativePO.getVoucherId());
            // 将关联的萤石子账号清掉
            accountDao.clearEzvizAccountById(relativePO.getAccountId());
            // 删除关联关系
            relativeVoucherAccountDao.deleteById(relativeId);
        }

    }

    @Override
    public List<VoucherNameDTO> getAllVoucherNameList() {
        return manageVoucherDao.getAllVoucherNameList();
    }

    @Override
    public ManageVoucherPO getVoucherByTreeId(BigDecimal voucherTreeId) {
        if (voucherTreeId == null) {
            throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "凭证组树结构id不能为空！");
        }
        ManageVoucherPO queryPO = new ManageVoucherPO();
        queryPO.setTreeId(voucherTreeId);
        List<ManageVoucherPO> voucherPOList = manageVoucherDao.queryAll(queryPO);
        if (CollectionUtils.isNotEmpty(voucherPOList)) {
            if (voucherPOList.size() > 1) {
                LOGGER.error("凭证组树结构存在大于等于2条的数据！voucherTreeId: {}", voucherTreeId);
            }
            return voucherPOList.get(0);
        }
        return null;
    }

    /**
     * 根据id获取凭证对象信息
     */
    private ManageVoucherPO getVoucherById(BigDecimal id) {
        if (id == null) {
            throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "id不能为空！");
        }
        ManageVoucherPO manageVoucherPO = manageVoucherDao.queryById(id);
        if (manageVoucherPO == null) {
            LOGGER.error("id: {} 对于凭证组不存在", id);
            throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "凭证组不存在！请刷新页面后再查看！");
        }
        return manageVoucherPO;
    }

    /**
     * 校验凭证组名称
     */
    private void validateVoucherName(String voucherName, BigDecimal id) {
        if (StringUtils.isBlank(voucherName)) {
            throw new BusinessException(CodeConstant.Http.PARAM_ERROR, "凭证组名称不能为空！");
        }
        ManageVoucherPO manageVoucherPO = manageVoucherDao.queryByVoucherName(voucherName);
        if (manageVoucherPO != null) {
            // 如果id为空说明是新增
            if (id == null) {
                throw new BusinessException(CodeConstant.Http.MOBILE_EXIST, "凭证组名称已被使用！");
            } else {
                // 编辑的话，id不一样说明不是自己
                if (!id.equals(manageVoucherPO.getId())) {
                    throw new BusinessException(CodeConstant.Http.MOBILE_EXIST, "凭证组名称已被使用！");
                } else {
                    // id一样的话，再判断名称是否有更改，没更改的话不修改
                    if (voucherName.equals(manageVoucherPO.getVoucherName())) {
                        throw new BusinessException(CodeConstant.Http.MOBILE_EXIST, "凭证组名称未更改！");
                    }
                }
            }
        }
    }

}
